Skip to content

[v2] Refactor: Move Form Groups to trie - #2326

Merged
LeCarbonator merged 5 commits into
TanStack:alphafrom
LeCarbonator:validator-state-refactor
Aug 12, 2026
Merged

[v2] Refactor: Move Form Groups to trie#2326
LeCarbonator merged 5 commits into
TanStack:alphafrom
LeCarbonator:validator-state-refactor

Conversation

@LeCarbonator

@LeCarbonator LeCarbonator commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Bug Fixes

    • Improved form-group validation, error visibility, and reset behavior.
    • Preserved form-group associations during field lifecycle changes and form resets.
    • Prevented stale validation results and incorrect removal of grouped fields.
    • Improved nested form-group handling in developer tools.
    • Ensured validation status accurately reflects activity at the form, group, and field levels.
  • Refactor

    • Streamlined form-group state management and field traversal behavior.
    • Improved consistency of grouped-field error reporting and validation lifecycle handling.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c8dc1b03-3d89-44ac-a367-7d98af60bf7c

📥 Commits

Reviewing files that changed from the base of the PR and between 235441a and 7f39e6d.

📒 Files selected for processing (4)
  • .changeset/tasty-humans-joke.md
  • packages/form-core/src/FieldApi/fieldTree.lib.ts
  • packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts
  • packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • .changeset/tasty-humans-joke.md
  • packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts
  • packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts

📝 Walkthrough

Walkthrough

Form groups now attach to field-trie nodes instead of a form registry. Group state, validation, errors, reset behavior, traversal, and devtools lookup use attached nodes and containing-group resolution.

Changes

Form group storage and validation

Layer / File(s) Summary
Field attachment and traversal
packages/form-core/src/FieldApi/*, packages/form-core/src/FormApi/FormApi.lib.ts, packages/form-devtools/src/bridge/fields/debug/*, packages/form-core/tests/FieldApi/*
Fields store group references and resolve containing groups through ancestor traversal. Traversal uses an explicit stop callback.
Backing-node group lifecycle
packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts, packages/form-core/src/FieldApi/FieldApi.lib.ts, packages/form-core/src/FieldApi/fieldTree.lib.ts, packages/form-core/src/FormApi/FormApi.lib.ts, packages/form-core/src/validation.lib.ts
Groups bind to backing trie nodes. Validation, routed errors, reset, cleanup, reattachment, and registry removal use those nodes.
Error metadata and visibility
packages/form-core/src/FieldApi/fieldState.lib.ts, packages/form-core/src/FormApi/formState.lib.ts, packages/form-core/src/FormApi/FormApi.public.ts, packages/form-core/src/validation.public.ts
Group validator errors use nullable metadata. Error aggregation and visibility use direct containing-group lookup.
Devtools and lifecycle validation
packages/form-devtools/src/bridge/fields/*, packages/form-devtools/tests/*, packages/form-core/tests/FormGroupApi/*, .changeset/tasty-humans-joke.md
Devtools use field-attached groups. Tests cover validation, movement, reset, cleanup, ownership, traversal, and debug output. A patch changeset was added.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FieldApi
  participant FieldTrie
  participant FormGroupApi
  participant Validation
  participant Devtools
  FieldApi->>FieldTrie: Attach form group to field node
  FieldApi->>FieldTrie: Resolve containing group
  FormGroupApi->>Validation: Run group validators
  Validation-->>FormGroupApi: Return group and field errors
  FormGroupApi->>FieldTrie: Store metadata and routed errors
  FieldApi->>Devtools: Emit field update
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided, so the required changes, checklist, and release impact sections are missing. Add the required sections, describe the changes and motivation, complete the checklist, and confirm the appropriate release impact and changeset.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: moving Form Groups to the field trie.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nx-cloud

nx-cloud Bot commented Aug 12, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 235441a

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 3m 58s View ↗
nx run-many --target=build --exclude=examples/** ✅ Succeeded 22s View ↗

☁️ Nx Cloud last updated this comment at 2026-08-12 06:21:41 UTC

@pkg-pr-new

pkg-pr-new Bot commented Aug 12, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-form

npm i https://pkg.pr.new/@tanstack/angular-form@2326

@tanstack/form-core

npm i https://pkg.pr.new/@tanstack/form-core@2326

@tanstack/form-devtools

npm i https://pkg.pr.new/@tanstack/form-devtools@2326

@tanstack/lit-form

npm i https://pkg.pr.new/@tanstack/lit-form@2326

@tanstack/preact-form

npm i https://pkg.pr.new/@tanstack/preact-form@2326

@tanstack/react-form

npm i https://pkg.pr.new/@tanstack/react-form@2326

@tanstack/react-form-devtools

npm i https://pkg.pr.new/@tanstack/react-form-devtools@2326

@tanstack/react-form-nextjs

npm i https://pkg.pr.new/@tanstack/react-form-nextjs@2326

@tanstack/react-form-start

npm i https://pkg.pr.new/@tanstack/react-form-start@2326

@tanstack/solid-form

npm i https://pkg.pr.new/@tanstack/solid-form@2326

@tanstack/solid-form-devtools

npm i https://pkg.pr.new/@tanstack/solid-form-devtools@2326

@tanstack/svelte-form

npm i https://pkg.pr.new/@tanstack/svelte-form@2326

@tanstack/vue-form

npm i https://pkg.pr.new/@tanstack/vue-form@2326

commit: 7f39e6d

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
.changeset/tasty-humans-joke.md (1)

2-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add @tanstack/form-devtools to the changeset.

This PR changes devtools source files (packages/form-devtools/src/bridge/fields/list.ts, detailSnapshot.ts, validatorsWithoutTriggers.ts, debug/schemaErrorOnUnmountedField.ts). Without an entry, that package is not released with the core change.

📦 Proposed changeset front matter
 ---
 '`@tanstack/form-core`': patch
+'`@tanstack/form-devtools`': patch
 ---
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/tasty-humans-joke.md at line 2, Update the changeset front matter
to include `@tanstack/form-devtools` alongside `@tanstack/form-core` with the
appropriate release bump, so the devtools source changes are included in the
release.
packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts (1)

104-224: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the deferred-validator scaffold.

The three tests repeat the same resolvers array, vi.fn promise validator, form, and group construction. A small helper that returns { form, group, validator, resolvers } would remove the duplication and keep each test focused on its lifecycle assertions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts` around lines 104
- 224, Extract the repeated deferred-validator setup from the three tests into a
shared helper returning form, group, validator, and resolvers. Reuse that helper
in each test while preserving the existing guestDetails configuration and
lifecycle assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/tasty-humans-joke.md:
- Line 5: Update the changelog entry text to use the correct plural possessive
for “Groups” and specify what is being accessed, preserving the intended meaning
of the Form Groups storage migration.

In `@packages/form-core/src/FieldApi/fieldState.lib.ts`:
- Line 32: Preserve per-group error ownership across the listed sites: in
packages/form-core/src/FieldApi/fieldState.lib.ts lines 32-32, replace the
single shared _formGroupValidatorErrors value with metadata that retains
separate buckets keyed by containing group; in
packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts lines 338-377, update
and clear only the current group’s bucket; and in
packages/form-core/src/FormApi/formState.lib.ts lines 132-145, aggregate all
active group-error buckets when computing field errors so nested and outer group
errors remain visible to the correct owner.

In `@packages/form-core/src/FieldApi/fieldTree.lib.ts`:
- Around line 331-334: Update the killField lifecycle so deleting a field that
backs an InternalFormGroupApi does not leave the live group pointing at a
detached node; either reject deletion, clean up the group, or reattach it to the
replacement live trie node. Preserve group attachment and validation for later
field creation under the same path, and keep _groupField and _formGroup
consistent.

In `@packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts`:
- Around line 235-242: Update FormGroupApi._cancelValidation so it no longer
resets the shared _groupField validation count. Track validation runs owned by
the group, including those started through _runFieldValidations, and on
cancellation remove only the group’s contributions while preserving
backing-field validator counts and isValidating state.

---

Nitpick comments:
In @.changeset/tasty-humans-joke.md:
- Line 2: Update the changeset front matter to include `@tanstack/form-devtools`
alongside `@tanstack/form-core` with the appropriate release bump, so the devtools
source changes are included in the release.

In `@packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts`:
- Around line 104-224: Extract the repeated deferred-validator setup from the
three tests into a shared helper returning form, group, validator, and
resolvers. Reuse that helper in each test while preserving the existing
guestDetails configuration and lifecycle assertions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d3793037-a07c-4684-bd99-716b352a569c

📥 Commits

Reviewing files that changed from the base of the PR and between 2d37d2d and 4275b58.

📒 Files selected for processing (20)
  • .changeset/tasty-humans-joke.md
  • packages/form-core/src/FieldApi/FieldApi.lib.ts
  • packages/form-core/src/FieldApi/fieldState.lib.ts
  • packages/form-core/src/FieldApi/fieldTraversal.lib.ts
  • packages/form-core/src/FieldApi/fieldTree.lib.ts
  • packages/form-core/src/FormApi/FormApi.lib.ts
  • packages/form-core/src/FormApi/FormApi.public.ts
  • packages/form-core/src/FormApi/formState.lib.ts
  • packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts
  • packages/form-core/src/validation.lib.ts
  • packages/form-core/src/validation.public.ts
  • packages/form-core/tests/FieldApi/fieldTraversal.spec.ts
  • packages/form-core/tests/FieldApi/meta.spec.ts
  • packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts
  • packages/form-devtools/src/bridge/fields/debug/schemaErrorOnUnmountedField.ts
  • packages/form-devtools/src/bridge/fields/detailSnapshot.ts
  • packages/form-devtools/src/bridge/fields/fieldDebug/validatorsWithoutTriggers.ts
  • packages/form-devtools/src/bridge/fields/list.ts
  • packages/form-devtools/tests/fieldDebugCases.test.ts
  • packages/form-devtools/tests/fieldDetailsBridge.test.ts

Comment thread .changeset/tasty-humans-joke.md Outdated
Comment thread packages/form-core/src/FieldApi/fieldState.lib.ts
Comment thread packages/form-core/src/FieldApi/fieldTree.lib.ts
Comment thread packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts Outdated
@codecov-commenter

codecov-commenter commented Aug 12, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 98.81657% with 2 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (alpha@2d37d2d). Learn more about missing BASE report.

Files with missing lines Patch % Lines
packages/form-core/src/FormApi/formState.lib.ts 71.42% 1 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@           Coverage Diff            @@
##             alpha    #2326   +/-   ##
========================================
  Coverage         ?   95.17%           
========================================
  Files            ?       64           
  Lines            ?     3482           
  Branches         ?      831           
========================================
  Hits             ?     3314           
  Misses           ?      160           
  Partials         ?        8           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/form-core/src/FieldApi/fieldTree.lib.ts`:
- Around line 272-274: Update the replacement cleanup loop around formGroups and
group._cancelValidation() to remove killed fields from _routedErrorFields,
filtering out any fields no longer live while preserving active routed error
fields. Add a regression test covering replacement of a routed field and
verifying the killed field is removed immediately.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 37a12217-15bf-448a-b552-f7799e58d31e

📥 Commits

Reviewing files that changed from the base of the PR and between 4275b58 and 235441a.

📒 Files selected for processing (5)
  • packages/form-core/src/FieldApi/FieldApi.lib.ts
  • packages/form-core/src/FieldApi/fieldTree.lib.ts
  • packages/form-core/src/FormApi/FormApi.lib.ts
  • packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts
  • packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts
💤 Files with no reviewable changes (1)
  • packages/form-core/src/FormApi/FormApi.lib.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/form-core/tests/FormGroupApi/FormGroupApi.spec.ts
  • packages/form-core/src/FormGroupApi/FormGroupApi.lib.ts

Comment thread packages/form-core/src/FieldApi/fieldTree.lib.ts
@LeCarbonator
LeCarbonator merged commit fc424c0 into TanStack:alpha Aug 12, 2026
9 checks passed
@LeCarbonator
LeCarbonator deleted the validator-state-refactor branch August 12, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants